import numpy as np
import requests
import io
import sys
from datetime import datetime
import os
import logging
from logging.handlers import RotatingFileHandler
import json
from json import JSONEncoder
import urllib.request

# 第三方库
try:
    from flask import Flask,request
except ModuleNotFoundError:
    print("缺少flask依赖！程序将尝试安装依赖！")
    os.system("pip3 install flask -i https://pypi.tuna.tsinghua.edu.cn/simple")
    os.execl(sys.executable, 'python3', __file__, *sys.argv)
from flask import Flask, render_template, request, redirect, url_for
from flask import send_from_directory, send_file

try:
    from PIL import Image
except ModuleNotFoundError:
    print("缺少PIL依赖！程序将尝试安装依赖！")
    os.system("pip3 install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple")
    os.execl(sys.executable, 'python3', __file__, *sys.argv)
from PIL import Image

try:
    from skimage.metrics import structural_similarity as ssim
except ModuleNotFoundError:
    print("缺少scikit-image依赖！程序将尝试安装依赖！")
    os.system("pip3 install scikit-image -i https://pypi.tuna.tsinghua.edu.cn/simple")
    os.execl(sys.executable, 'python3', __file__, *sys.argv)
from skimage.metrics import structural_similarity as ssim


app=Flask(__name__)

def return_msg(code=200, msg="ok", data=None):
    """
    返回数据
    """
    return {
        "code": code,
        "msg": msg,
        "data": data,
    }

def customStudentDecoder(studentDict):
    return namedtuple('X', studentDict.keys())(*studentDict.values())

@app.route('/ccb/status',methods=['POST'])
def status():
    return return_msg()

@app.route('/ccb/jigsaw',methods=['POST'])
def jigsaw():
    try:
        result = request.get_json()
        if(result['status']=='success'):
            img = result['data']['img']
            thumb = result['data']['thumb']
            ptImgs =[]
            for n in thumb.keys():
                ptImgs.append({'n':n,'url':thumb.get(n)})
            loadImage(ptImgs)
            crop_width = ptImgs[0]['width']
            crop_height = ptImgs[0]['height']
            imgWidth = ptImgs[0]['width']*3
            imgHeight = ptImgs[0]['height']*3
            # 将原图拉伸至 width*3， height*3 ,然后分割成3*3个图块
            largeImg = readImage(img, imgWidth, imgHeight)
            # 切割后的图像列表
            cropped_images = []
            # 循环切割图像
            for i in range(3):
                for j in range(3):
                    # 计算切割区域的坐标
                    left = j * crop_width
                    upper = i * crop_height
                    right = left + crop_width
                    lower = upper + crop_height
                    # 切割图像
                    cropped_image = largeImg.crop((left, upper, right, lower))
                    cropped_images.append(cropped_image)
  
            o = []
            for ci, c in enumerate(cropped_images):
                cp = np.array(c.convert("L"))
                m = 0
                i = -1
                for index, bi in enumerate(ptImgs):
                    similarity = ssim(cp, bi['aryImg'])
                    print(f'对比 {ci} :: {index} , 相似度：{similarity}')
                    if similarity > m:
                        m = similarity
                        i = index
                o.append(i)

            nList = []
            for p in o:
                nList.append(ptImgs[p]['n'])
            nResult =  ",".join(nList)
            print(f'拼图识别, 顺序：{nResult}')
            return return_msg(data=nResult)
        else:
            app.logger.error(f'拼图识图失败, 图片数据：{request.get_json()}')
            return return_msg(code=500, msg= '拼图识图失败！' )
    except Exception as e:
        app.logger.error(f'图片数据：{request.get_json()}')
        app.logger.error('拼图识图失败！', e)
        return return_msg(code=500, msg= f'拼图识图失败！{e}' )

def loadImage(ptImgs):
        for pt in ptImgs:
            img = readImage(pt['url'])
            pt['img']=img
            pt['aryImg']=np.array(img.convert("L"))
            trows,tcols = pt['aryImg'].shape[:2]  #获得图片的宽度
            pt['width']=trows
            pt['height']=tcols

def readImage(url, width=0, height=0):
    img = Image.open(io.BytesIO(requests.get(url).content))
    if(width>0 and height>0):
        print(f'图片尺寸重置 ，width: {width} , height: {height}')
        return img.resize((width, height))
    return img


if(__name__=='__main__'):
    # 设置日志的记录等级
    logging.basicConfig(level=logging.DEBUG) # 调试debug级
    # 创建日志记录器，指明日志保存的路径（前面的logs为文件的名字，需要我们手动创建，后面则会自动创建）、每个日志文件的最大大小、保存的日志文件个数上限。
    # file_log_handler = RotatingFileHandler("../logs/log", maxBytes=1024*1024*100, backupCount=10)
    file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024*1024*2, backupCount=10, encoding="utf-8", mode="a")
    # 创建日志记录的格式               日志等级    输入日志信息的文件名   行数       日志信息
    formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
    # 为刚创建的日志记录器设置日志记录格式
    file_log_handler.setFormatter(formatter)
    # 为全局的日志工具对象（flask app使用的）添加日志记录器
    logging.getLogger().addHandler(file_log_handler)
    # host='0.0.0.0' ，外网通过公网ip可访问， 如只想本机访问，改为本内网机IP即可
    app.run(host='0.0.0.0',port = '8998')